/**   
 * @Title: HealthService.java 
 * @Package cn.edu.cdtu.healthclient.service
 * @Description: 系统后台实现 
 * @author 
 * @date 
 * @version V0.5   
 */
package cn.edu.cdtu.healthclient.service;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import cn.edu.cdtu.healthclient.task.ServiceTaskQueue;
import cn.edu.cdtu.healthclient.utils.ConnectUtil;

/** 
 * @ClassName: HealthService 
 * @Description: 系统后台
 * 				用于存储运行期内存常驻数据对象和应用状态；
 * 				为各个Activity提供一个统一的通信手段；
 * 				新增：提供后台存储、执行任务(线程)的接口
 * @author 
 * @date
 *  
 */
public class HealthService extends Service {
	
	/*
	 * 本Service的Action配置名称，与AndroidManifest.xml的配置统一
	 * ACTION为一个标签 用来启动该后台Service。
	 */
	public static final String ACTION = "cn.edu.scu.healthclient.service.HealthService";
	/*
	 * 网络通信中统一使用的HttpClient，用于自律式维护Session机制和Cookie机制
	 */
	private volatile HttpClient httpClient;

	/**
	 * 
	 * @ClassName: AttributeSet 
	 * @Description: 对象数据单元，用于存储对象数据与其名称
	 * @author 
	 * @date 
	 *
	 */
	private class AttributeSet<T>{
		
		public String attributeNameString;//对象名称
		public T attributeObject;//对象数据
		/** 
		 * @Title: AttributeSet
		 * @Description: TODO
		 * @throws 
		 *
		 * @param attributeNameString
		 * @param attributeObject
		 */
		public AttributeSet(String attributeNameString, T attributeObject) {
			this.attributeNameString = attributeNameString;
			this.attributeObject = attributeObject;
		}
		
	}
	/*
	 * 对象数据集，存储设置到后台的对象数据或状态信息
	 */
	private volatile List<AttributeSet<Object>> attributeList;
	/*
	 * 后台任务(线程)队列
	 */
	private volatile ServiceTaskQueue taskThreads;
	/**
	 * 
	 * @ClassName: HealthBinder 
	 * @Description: 用于实现Service与前台通信的Binder
	 * @author 
	 * @date 
	 *
	 */
	public class HealthBinder extends Binder{
		/**
		 * 
		 * @Title: getHttpClient 
		 * @Description: 通信接口：获取统一HttpClient
		 * @return HttpClient
		 * @throws 
		 *
		 * @return
		 */
		public synchronized HttpClient getHttpClient(){
			return httpClient;
		}
		/**
		 * 
		 * @Title: setAttribute 
		 * @Description: 通信接口：存储对象数据，同名覆盖
		 * @return void
		 * @throws 
		 *
		 * @param name 存储的数据名称
		 * @param attribute 存储的对象数据
		 */
		public synchronized void setAttribute(final String name,Object attribute){
			boolean isExisted = false;
			for (AttributeSet<Object> attributeSet : attributeList) {
				if(attributeSet.attributeNameString.equals(name)){
					isExisted = true;
					attributeSet.attributeObject = attribute;
					break;
				}
			}
			if(!isExisted){
				attributeList.add(new AttributeSet<Object>(name, attribute));
			}
		}
		/**
		 * 
		 * @Title: getAttribute 
		 * @Description: 按名称获取相应的数据对象
		 * @return Object
		 * @throws 
		 *
		 * @param name 存储的数据的名称
		 * @return
		 */
		public synchronized Object getAttribute(final String name){
			Object tempObject = null;
			for (AttributeSet<Object> attributeSet : attributeList) {
				if(attributeSet.attributeNameString.equals(name)){
					tempObject = attributeSet.attributeObject;
					break;
				}
			}
			return tempObject;
		}
		/**
		 * 
		 * @Title: setTask 
		 * @Description: 设置任务到任务列表中(线程)，同名替换
		 * @return void
		 * @throws 
		 *
		 * @param taskName
		 * @param taskThread
		 */
		public void setTask(final String taskName, Thread taskThread){
			taskThreads.setTask(taskName, taskThread);
		}
		/**
		 * 
		 * @Title: startTask 
		 * @Description: 异步启动指定名称的任务(线程)
		 * @return void
		 * @throws 
		 *
		 * @param taskName
		 */
		public void startTask(final String taskName){
			taskThreads.startTask(taskName);
		}
		/**
		 * 
		 * @Title: startTask 
		 * @Description: 延迟启动指定任务
		 * @return void
		 * @throws 
		 *
		 * @param taskName
		 * @param delay
		 */
		public synchronized void startTask(final String taskName, final long delay){
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					// TODO Auto-generated method stub
					try {
						Thread.sleep(delay);
						startTask(taskName);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}).start();
		}
	}
	/*
	 * Service与前台通信对象
	 */
	private final HealthBinder binder = new HealthBinder();
	
	/* (non-Javadoc)
	 * <p>Title: onBind</p> 
	 * <p>Description: </p> 
	 * @param intent
	 * @return 
	 * @see android.app.Service#onBind(android.content.Intent)
	 */
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return binder;
	}

	/* (non-Javadoc)
	 * <p>Title: onCreate</p> 
	 * <p>Description: </p>  
	 * @see android.app.Service#onCreate()
	 */
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
		//实例化一个HttpParams对象，负责为Http设置各种初始参数。
		final HttpParams httpParams = new BasicHttpParams();
		//设置连接的时间限制，超过该时间 则连接超时。
		ConnManagerParams.setTimeout(httpParams, 
				ConnectUtil.HealthServerContect.DEFAULT_CONN_MANAGER_TIMEOUT);
		
		HttpConnectionParams.setConnectionTimeout(httpParams, 
				ConnectUtil.HealthServerContect.DEFAULT_CONNECT_TIMEOUT);
		HttpConnectionParams.setSoTimeout(httpParams, 
				ConnectUtil.HealthServerContect.DEFAULT_SOCKET_TIMEOUT);
		ConnManagerParams.setMaxConnectionsPerRoute(httpParams,
				new ConnPerRouteBean(
						ConnectUtil.HealthServerContect.DEFAULT_HOST_CONNECTIONS)); 
		ConnManagerParams.setMaxTotalConnections(httpParams, 
				ConnectUtil.HealthServerContect.DEFAULT_MAX_CONNECTIONS);
		HttpProtocolParams.setUseExpectContinue(httpParams, true);
		HttpConnectionParams.setStaleCheckingEnabled(httpParams, 
				ConnectUtil.HealthServerContect.STALE_CHECKING_ENABLED);
        HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);  
        HttpProtocolParams.setContentCharset(httpParams, HTTP.UTF_8); 
        HttpClientParams.setRedirecting(httpParams, false);
        HttpProtocolParams.setUserAgent(httpParams, 
        		ConnectUtil.HealthServerContect.DEFAULT_AGENT);
        HttpConnectionParams.setTcpNoDelay(httpParams, true); 
        HttpConnectionParams.setSocketBufferSize(httpParams, 
        		ConnectUtil.HealthServerContect.DEFAULT_SOCKET_BUFFER_SIZE);
        SchemeRegistry schemeRegistry = new SchemeRegistry();  
        schemeRegistry.register(
        		new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));  
        schemeRegistry.register(
        		new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
        ClientConnectionManager manager = 
        		new ThreadSafeClientConnManager(httpParams, schemeRegistry);  
        httpClient = new DefaultHttpClient(manager, httpParams);
		attributeList = 
				new ArrayList<HealthService.AttributeSet<Object>>();
		taskThreads = new ServiceTaskQueue();
	}

	/* (non-Javadoc)
	 * <p>Title: onStartCommand</p> 
	 * <p>Description: </p> 
	 * @param intent
	 * @param flags
	 * @param startId
	 * @return 
	 * @see android.app.Service#onStartCommand(android.content.Intent, int, int)
	 */
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		// TODO Auto-generated method stub
		if(!taskThreads.isRunning()){
			taskThreads.start();
		}
		return super.onStartCommand(intent, flags, startId);
	}

	/* (non-Javadoc)
	 * <p>Title: onDestroy</p> 
	 * <p>Description: </p>  
	 * @see android.app.Service#onDestroy()
	 */
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		taskThreads.shutdownTaskQueue();
		super.onDestroy();
	}
	
}
